﻿using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Business.Machine.Enums;
using RotovapPlatform.Domain.Business.Storage.Entities;
using RotovapPlatform.Domain.Common;
using RotovapPlatform.Domain.Services.Experiments;
using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using RotovapPlatform.Domain.Business.Interfaces;
using RotovapPlatform.Domain.Business.Recipes.Entities;
using System.ComponentModel.DataAnnotations;
using RotovapPlatform.Domain.Recipes.Services;
using RotovapPlatform.Domain.Services.Storages;
using static RotovapPlatform.Domain.Business.Machine.Enums.ExperimentConfigEnums;
using System.Collections.ObjectModel;
using RotovapPlatform.Domain.Business.Storage.Enums;

namespace RotovapPlatform.Domain.Services.Scheduling
{
	/// <summary>
	/// 任务调度领域服务实现
	/// </summary>
	public class TaskSchedulingDomainService : ITaskSchedulingDomainService
	{
		private readonly ILogger<TaskSchedulingDomainService> _logger;
		private readonly IExperimentGroupRepository _experimentGroupRepository;
		private readonly IExperimentRepository _experimentRepository;
		private readonly IRecipeDomainService _recipeDomainService;
		private readonly IStorageDomainService _storageDomainService;

		// 当前正在执行的实验
		private Experiment _currentExperiment;
		// 当前正在执行的实验组
		private ExperimentGroup _currentExperimentGroup;

		/// <summary>
		/// 当前实验变更事件
		/// </summary>
		public event EventHandler<CurrentExperimentChangedEventArgs> CurrentExperimentChanged;

		/// <summary>
		/// 当前实验组变更事件
		/// </summary>
		public event EventHandler<CurrentExperimentGroupChangedEventArgs> CurrentExperimentGroupChanged;

		public TaskSchedulingDomainService(
			ILogger<TaskSchedulingDomainService> logger,
			IExperimentGroupRepository experimentGroupRepository,
			IExperimentRepository experimentRepository,
			IRecipeDomainService recipeDomainService,
			IStorageDomainService storageDomainService)
		{
			_logger = logger;
			_experimentGroupRepository = experimentGroupRepository;
			_experimentRepository = experimentRepository;
			_recipeDomainService = recipeDomainService;
			_storageDomainService = storageDomainService;
		}

		/// <summary>
		/// 分解实验组为单个实验任务
		/// </summary>
		/// <param name="experimentGroupId">实验组ID</param>
		/// <returns>分解后的实验列表</returns>
		public async Task<List<Experiment>> DecomposeExperimentGroupDomainAsync(Guid experimentGroupId)
		{
			try
			{
				_logger.LogInformation($"开始分解实验组 {experimentGroupId} 为单个实验任务");

				// 获取实验组
				var experimentGroup = await _experimentGroupRepository.GetByIdAsync(experimentGroupId);
				if (experimentGroup == null)
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不存在");
					return new List<Experiment>();
				}

				// 检查实验组是否包含配方
				if (experimentGroup.Recipes == null || !experimentGroup.Recipes.Any())
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不包含任何配方");
					return new List<Experiment>();
				}

				// 分解实验组为单个实验任务
				experimentGroup.CreateExperimentsFromRecipes();

				// 保存实验到数据库
				var experiments = experimentGroup.Experiments.ToList();
				_logger.LogInformation($"实验组 {experimentGroupId} 分解完成，共生成 {experiments.Count} 个实验，准备保存到数据库");

				foreach (var experiment in experiments)
				{
					try
					{
						// 重要：断开实验与配方的导航属性连接，防止EF尝试重新插入配方
						// 保留RecipeId外键引用，但将Recipe导航属性设为null
						var recipeId = experiment.RecipeId;
						var recipe = experiment.Recipe; // 临时保存Recipe引用
						_logger.LogDebug($"准备保存实验 {experiment.ExperimentId}，关联的配方ID: {recipeId}");

						// 完全断开Recipe导航属性
						experiment.Recipe = null;

						// 检查实验是否已存在
						var existingExperiment = await _experimentRepository.GetByIdAsync(experiment.ExperimentId);
						if (existingExperiment == null)
						{
							_logger.LogDebug($"实验 {experiment.ExperimentId} 不存在，准备添加");
							await _experimentRepository.AddAsync(experiment);
							_logger.LogInformation($"已添加实验 {experiment.ExperimentId}");
						}
						else
						{
							_logger.LogDebug($"实验 {experiment.ExperimentId} 已存在，准备更新");
							await _experimentRepository.UpdateAsync(experiment);
							_logger.LogInformation($"已更新实验 {experiment.ExperimentId}");
						}

						// 保存完成后，恢复Recipe引用，但不触发数据库操作
						experiment.Recipe = recipe;
						experiment.RecipeId = recipeId;
					}
					catch (Exception ex)
					{
						_logger.LogError(ex, $"保存实验 {experiment.ExperimentId} 时发生错误: {ex.Message}");
						// 继续处理其他实验，而不是立即终止整个过程
						continue;
					}
				}

				// 更新实验组，但不更新关联的实验（已单独保存）
				await _experimentGroupRepository.UpdateAsync(experimentGroup, false);
				_logger.LogInformation($"已更新实验组 {experimentGroupId}，共包含 {experiments.Count} 个实验");

				return experiments;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"分解实验组 {experimentGroupId} 时发生错误");
				throw;
			}
		}

		/// <summary>
		/// 分解实验组为单个实验任务（不保存到数据库，仅用于UI显示）
		/// </summary>
		/// <param name="experimentGroupId">实验组ID</param>
		/// <returns>分解后的实验列表</returns>
		public async Task<List<Experiment>> DecomposeExperimentGroupWithoutSavingAsync(Guid experimentGroupId)
		{
			try
			{
				_logger.LogInformation($"开始分解实验组 {experimentGroupId} 为单个实验任务（不保存到数据库）");

				// 获取实验组
				var experimentGroup = await _experimentGroupRepository.GetByIdAsync(experimentGroupId);
				if (experimentGroup == null)
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不存在");
					return new List<Experiment>();
				}

				// 检查实验组是否包含配方
				if (experimentGroup.Recipes == null || !experimentGroup.Recipes.Any())
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不包含任何配方");
					return new List<Experiment>();
				}

				// 分解实验组为单个实验任务
				experimentGroup.CreateExperimentsFromRecipes();

				// 返回实验列表，但不保存到数据库
				var experiments = experimentGroup.Experiments.ToList();
				_logger.LogInformation($"已分解实验组 {experimentGroupId}，共包含 {experiments.Count} 个实验（未保存到数据库）");

				return experiments;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"分解实验组 {experimentGroupId} 时发生错误");
				throw;
			}
		}

		/// <summary>
		/// 验证实验组配方
		/// </summary>
		/// <param name="experimentGroupId">实验组ID</param>
		/// <returns>验证结果</returns>
		public async Task<ValidationResult> ValidateExperimentGroupDomainAsync(string experimentGroupId)
		{
			try
			{
				_logger.LogInformation($"开始验证实验组 {experimentGroupId} 的配方");

				// 解析实验组ID
				if (!Guid.TryParse(experimentGroupId, out Guid groupId))
				{
					_logger.LogWarning($"实验组ID {experimentGroupId} 格式不正确");
					return new ValidationResult($"实验组ID格式不正确: {experimentGroupId}");
				}

				// 获取实验组
				var experimentGroup = await _experimentGroupRepository.GetByIdAsync(groupId);
				if (experimentGroup == null)
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不存在");
					return new ValidationResult($"实验组不存在: {experimentGroupId}");
				}

				// 检查实验组是否包含配方
				if (experimentGroup.Recipes == null || !experimentGroup.Recipes.Any())
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 不包含任何配方");
					return new ValidationResult($"实验组不包含任何配方: {experimentGroupId}");
				}

				// 验证每个配方
				var errors = new List<string>();
				foreach (var recipe in experimentGroup.Recipes)
				{
					// 验证配方基本信息
					if (string.IsNullOrEmpty(recipe.ExperimentName))
					{
						errors.Add($"配方 {recipe.RecipeId} 缺少实验名称");
					}

					// 使用RecipeDomainService验证每个配方
					var (isValid, errorMessage) = await _recipeDomainService.ValidateRecipeAsync(recipe);
					if (!isValid)
					{
						errors.Add($"配方 {recipe.ExperimentName} ({recipe.RecipeId}) 验证失败: {errorMessage}");
					}
				}

				// 验证物料位置是否有重复
				var (locationsValid, locationsError) = await _recipeDomainService.ValidateMaterialLocationsAsync(experimentGroup.Recipes);
				if (!locationsValid)
				{
					errors.Add($"物料位置验证失败: {locationsError}");
				}

				// 计算所需瓶子数量
				// 1. 旋蒸瓶数量：按照瓶子类型分类统计
				var rotovapBottles500ml = experimentGroup.Recipes.Count(r => r.RotovapParameters?.RotaryBottleType == RotaryBottleSize.RotaryBottle_500ml);
				var rotovapBottles1000ml = experimentGroup.Recipes.Count(r => r.RotovapParameters?.RotaryBottleType == RotaryBottleSize.RotaryBottle_1000ml);

				// 2. 离心瓶数量：产物参数的数量 + 旋蒸残液是否收集
				int requiredCentrifugeBottles = experimentGroup.Recipes.Sum(r =>
					(r.RotovapParameters?.ProductParameters?.Count ?? 0) +
					(r.RotovapParameters?.ResidualLiquidParameters?.IsResidualLiquidCollect == true ? 1 : 0));

				// 3. 取样瓶数量：产物参数中选择取样的数量 + 旋蒸残液取样
				int requiredSampleBottles = experimentGroup.Recipes.Sum(r =>
					(r.RotovapParameters?.ProductParameters?.Count(p => p.IsSampling) ?? 0) +
					(r.RotovapParameters?.ResidualLiquidParameters?.IsSampling == true ? 1 : 0));

				// 验证瓶子数量是否足够
				var (bottlesValid, bottlesError) = await _storageDomainService.ValidateBottleAvailabilityAsync(
					rotovapBottles500ml,
					rotovapBottles1000ml,
					requiredCentrifugeBottles,
					requiredSampleBottles);

				if (!bottlesValid)
				{
					errors.Add($"瓶子数量验证失败: {bottlesError}");
				}

				// 返回验证结果
				if (errors.Any())
				{
					_logger.LogWarning($"实验组 {experimentGroupId} 的配方验证失败，共有 {errors.Count} 个错误");
					return new ValidationResult(string.Join(Environment.NewLine, errors));
				}

				_logger.LogInformation($"实验组 {experimentGroupId} 的配方验证通过");
				return ValidationResult.Success;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"验证实验组 {experimentGroupId} 的配方时发生错误");
				return new ValidationResult($"验证过程中发生错误: {ex.Message}");
			}
		}

		/// <summary>
		/// 获取当前正在执行的实验
		/// </summary>
		/// <returns>当前实验，若无则返回null</returns>
		public Task<Experiment> GetCurrentExperimentAsync()
		{
			return Task.FromResult(_currentExperiment);
		}

		/// <summary>
		/// 获取当前正在执行的实验组
		/// </summary>
		/// <returns>当前实验组，若无则返回null</returns>
		public Task<ExperimentGroup> GetCurrentExperimentGroupAsync()
		{
			return Task.FromResult(_currentExperimentGroup);
		}

		/// <summary>
		/// 触发当前实验变更事件
		/// </summary>
		/// <param name="currentExperiment">当前实验</param>
		protected virtual void OnCurrentExperimentChanged(Experiment currentExperiment)
		{
			try
			{
				_logger.LogInformation($"触发当前实验变更事件: {currentExperiment?.ExperimentId}");
				CurrentExperimentChanged?.Invoke(this, new CurrentExperimentChangedEventArgs(currentExperiment));
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "触发当前实验变更事件时发生错误");
			}
		}

		/// <summary>
		/// 触发当前实验组变更事件
		/// </summary>
		/// <param name="experimentGroup">当前实验组</param>
		protected virtual void OnCurrentExperimentGroupChanged(ExperimentGroup experimentGroup)
		{
			_logger.LogInformation($"当前实验组变更为: {experimentGroup?.GroupId}");
			CurrentExperimentGroupChanged?.Invoke(this, new CurrentExperimentGroupChangedEventArgs(experimentGroup.GroupId));
		}

		/// <summary>
		/// 设置当前要执行的实验和实验组
		/// </summary>
		/// <param name="experiment">要执行的实验</param>
		/// <param name="experimentGroup">实验所属的实验组</param>
		/// <returns>操作结果</returns>
		public async Task<OperationResult> SetCurrentExperimentAndGroupAsync(Experiment experiment, ExperimentGroup experimentGroup)
		{
			try
			{
				_logger.LogInformation($"领域服务设置当前实验 {experiment?.ExperimentId} 和实验组 {experimentGroup?.GroupId}");

				// 验证参数
				if (experiment == null)
				{
					_logger.LogWarning("设置当前实验和实验组时，实验参数为null");
					return new OperationResult { Success = false, Message = "实验参数为null" };
				}

				if (experimentGroup == null)
				{
					_logger.LogWarning("设置当前实验和实验组时，实验组参数为null");
					return new OperationResult { Success = false, Message = "实验组参数为null" };
				}

				// 验证实验是否属于实验组
				if (experiment.ExperimentGroupId != experimentGroup.GroupId)
				{
					_logger.LogWarning($"实验 {experiment.ExperimentId} 不属于实验组 {experimentGroup.GroupId}");
					return new OperationResult { Success = false, Message = $"实验 {experiment.ExperimentId} 不属于实验组 {experimentGroup.GroupId}" };
				}

				// 设置当前实验和实验组
				_currentExperiment = experiment;
				_currentExperimentGroup = experimentGroup;

				// 触发事件
				OnCurrentExperimentChanged(_currentExperiment);
				OnCurrentExperimentGroupChanged(_currentExperimentGroup);

				_logger.LogInformation($"已设置当前实验 {experiment.ExperimentId} 和实验组 {experimentGroup.GroupId}");
				return new OperationResult { Success = true, Message = $"已设置当前实验 {experiment.ExperimentName} 和实验组 {experimentGroup.GroupName}" };
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置当前实验和实验组时发生错误");
				return new OperationResult { Success = false, Message = $"设置当前实验和实验组时发生错误: {ex.Message}" };
			}
		}

		/// <summary>
		/// 设置当前要执行的实验
		/// </summary>
		/// <param name="experiment">要执行的实验</param>
		/// <returns>操作结果</returns>
		public async Task<OperationResult> SetCurrentExperimentAsync(Experiment experiment)
		{
			try
			{
				_logger.LogInformation($"领域服务设置当前实验 {experiment?.ExperimentId}");

				// 验证参数
				if (experiment == null)
				{
					_logger.LogWarning("设置当前实验时，实验参数为null");
					return new OperationResult { Success = false, Message = "实验参数为null" };
				}

				// 检查实验状态
				if (experiment.Status != ExperimentStatus.Running)
				{
					_logger.LogWarning($"实验 {experiment.ExperimentId} 的状态不是运行中");
					// 不返回错误，只是记录日志，因为可能存在状态更新延迟
				}

				// 设置当前实验
				_currentExperiment = experiment;

				// 触发事件
				OnCurrentExperimentChanged(_currentExperiment);

				_logger.LogInformation($"已设置当前实验 {experiment.ExperimentId}");
				return new OperationResult { Success = true, Message = $"已设置当前实验 {experiment.ExperimentName}" };
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置当前实验时发生错误");
				return new OperationResult { Success = false, Message = $"设置当前实验时发生错误: {ex.Message}" };
			}
		}

		/// <summary>
		/// 启动实验组
		/// </summary>
		/// <param name="experimentGroup">要启动的实验组</param>
		/// <returns>操作结果</returns>
		public async Task<OperationResult> StartExperimentGroupDomainAsync(ExperimentGroup experimentGroup)
		{
			try
			{
				_logger.LogInformation($"领域服务启动实验组 {experimentGroup.GroupId}");

				// 1. 验证实验组配方
				var validationResult = await ValidateExperimentGroupDomainAsync(experimentGroup.GroupId.ToString());
				if (validationResult != ValidationResult.Success)
				{
					_logger.LogWarning($"实验组 {experimentGroup.GroupId} 配方验证失败: {validationResult.ErrorMessage}");
					return new OperationResult { Success = false, Message = $"配方验证失败: {validationResult.ErrorMessage}" };
				}

				// 2. 分解实验组为单个实验任务
				if (experimentGroup.Experiments == null || !experimentGroup.Experiments.Any())
				{
					_logger.LogInformation($"实验组 {experimentGroup.GroupId} 尚未分解为实验，正在进行分解...");
					var experiments = await DecomposeExperimentGroupDomainAsync(experimentGroup.GroupId);
					if (experiments == null || !experiments.Any())
					{
						_logger.LogWarning($"实验组 {experimentGroup.GroupId} 分解失败或未生成有效实验");
						return new OperationResult { Success = false, Message = "实验组分解失败或未生成有效实验" };
					}
					// 将List<Experiment>转换为ObservableCollection<Experiment>
					experimentGroup.Experiments = new ObservableCollection<Experiment>(experiments);
				}

				// 3. 为实验组分配所有资源
				var allocationResult = await AllocateResourcesForExperimentGroupAsync(experimentGroup);
				if (!allocationResult.Success)
				{
					_logger.LogWarning($"实验组 {experimentGroup.GroupId} 资源分配失败: {allocationResult.Message}");
					return allocationResult;
				}

				// 4. 更新实验组状态
				experimentGroup.Status = ExperimentGroupStatus.Running;
				experimentGroup.ExecutionStartTime = DateTime.Now;
				await _experimentGroupRepository.UpdateAsync(experimentGroup);

				// 5. 设置当前实验组并触发事件
				_currentExperimentGroup = experimentGroup;
				OnCurrentExperimentGroupChanged(_currentExperimentGroup);

				_logger.LogInformation($"实验组 {experimentGroup.GroupId} 启动成功");
				return new OperationResult { Success = true, Message = "实验组启动成功" };
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"启动实验组 {experimentGroup?.GroupId} 时发生错误");
				return new OperationResult { Success = false, Message = $"启动实验组时发生错误: {ex.Message}" };
			}
		}

		/// <summary>
		/// 为实验组分配所有资源
		/// </summary>
		/// <param name="experimentGroup">实验组</param>
		/// <returns>操作结果</returns>
		private async Task<OperationResult> AllocateResourcesForExperimentGroupAsync(ExperimentGroup experimentGroup)
		{
			try
			{
				_logger.LogInformation($"开始为实验组 {experimentGroup.GroupId} 分配资源");

				// 第一步：预留物料位置
				// 遍历所有实验的MaterialLocations并预占位
				if (experimentGroup.Experiments != null && experimentGroup.Experiments.Any())
				{
					_logger.LogInformation($"实验组包含 {experimentGroup.Experiments.Count} 个实验，开始处理物料位置预留");

					foreach (var experiment in experimentGroup.Experiments)
					{
						if (experiment.ExecutionParameters?.MaterialLocations != null &&
							experiment.ExecutionParameters.MaterialLocations.Any())
						{
							_logger.LogInformation($"实验 {experiment.ExperimentId} 包含 {experiment.ExecutionParameters.MaterialLocations.Count} 个物料位置");

							foreach (var position in experiment.ExecutionParameters.MaterialLocations)
							{
								// 获取对应的货架位置，强制从数据库获取最新数据
								var location = await _storageDomainService.GetShelfLocationAsync(LocationCode.Shelf, position);
								if (location != null)
								{
									// 只有当IsReserved为0时才进行预占位
									if (location.IsReserved == 0)
									{
										// 使用UpdateIsReserved方法设置预占位状态
										location.UpdateIsReserved(1);

										// 更新数据库
										await _storageDomainService.UpdateShelfLocationAsync(location);
										_logger.LogInformation($"已将货架位置 {position} 设置为预占位状态");
									}
									else
									{
										_logger.LogWarning($"货架位置 {position} 已被预占位（状态值: {location.IsReserved}），跳过");
									}
								}
								else
								{
									_logger.LogWarning($"找不到货架位置 {position}，无法预占位");
								}
							}
						}
						else
						{
							_logger.LogWarning($"实验 {experiment.ExperimentId} 没有指定物料位置");
						}
					}
				}

				// 第二步：计算并预留各类型空瓶的数量
				// 根据每个实验的执行配方统计所需空瓶数量
				int rotovapBottles500ml = 0;
				int rotovapBottles1000ml = 0;
				int centrifugeBottles500ml = 0;
				int sampleBottles8ml = 0;

				// 统计所需瓶子数量
				if (experimentGroup.Recipes != null && experimentGroup.Recipes.Any())
				{
					// 从配方中获取旋蒸瓶类型
					rotovapBottles500ml = experimentGroup.Recipes.Count(r => r.RotovapParameters?.RotaryBottleType == RotaryBottleSize.RotaryBottle_500ml);
					rotovapBottles1000ml = experimentGroup.Recipes.Count(r => r.RotovapParameters?.RotaryBottleType == RotaryBottleSize.RotaryBottle_1000ml);

					// 离心瓶数量：产物参数的数量 + 旋蒸残液是否收集
					centrifugeBottles500ml = experimentGroup.Recipes.Sum(r =>
						(r.RotovapParameters?.ProductParameters?.Count ?? 0) +
						(r.RotovapParameters?.ResidualLiquidParameters?.IsResidualLiquidCollect == true ? 1 : 0));

					// 取样瓶数量：产物参数中选择取样的数量 + 旋蒸残液取样
					sampleBottles8ml = experimentGroup.Recipes.Sum(r =>
						(r.RotovapParameters?.ProductParameters?.Count(p => p.IsSampling) ?? 0) +
						(r.RotovapParameters?.ResidualLiquidParameters?.IsSampling == true ? 1 : 0));
				}

				_logger.LogInformation($"实验组需要的空瓶数量: 500ml旋蒸瓶={rotovapBottles500ml}, 1000ml旋蒸瓶={rotovapBottles1000ml}, " +
									   $"500ml离心瓶={centrifugeBottles500ml}, 8ml取样瓶={sampleBottles8ml}");

				// 预留500ml旋蒸空瓶
				await ReserveBottlesAsync(ItemType.Rotovap_500ml, rotovapBottles500ml);

				// 预留1000ml旋蒸空瓶
				await ReserveBottlesAsync(ItemType.Rotovap_1000ml, rotovapBottles1000ml);

				// 预留500ml离心空瓶
				await ReserveBottlesAsync(ItemType.CentrifugeBottle_500ml, centrifugeBottles500ml);

				// 预留8ml取样空瓶
				await ReserveBottlesAsync(ItemType.SampleBottle_8ml, sampleBottles8ml);

				_logger.LogInformation($"实验组 {experimentGroup.GroupId} 资源分配完成");
				return new OperationResult { Success = true, Message = "资源分配成功" };
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"为实验组 {experimentGroup?.GroupId} 分配资源时出错: {ex.Message}");
				return new OperationResult { Success = false, Message = $"分配资源时出错: {ex.Message}" };
			}
		}

		/// <summary>
		/// 预留指定类型和数量的瓶子
		/// </summary>
		/// <param name="bottleType">瓶子类型</param>
		/// <param name="count">数量</param>
		private async Task ReserveBottlesAsync(ItemType bottleType, int count)
		{
			if (count <= 0)
				return;

			_logger.LogInformation($"开始预留 {count} 个 {bottleType} 类型的瓶子");

			// 获取已有可用瓶子的位置 - 强制刷新确保获取最新数据
			var bottleLocations = await _storageDomainService.GetAvailableBottleLocationsAsync(bottleType);

			// 获取可用的空位置 - 强制刷新确保获取最新数据
			var emptyLocations = await _storageDomainService.GetAvailableShelfLocationsForItemTypeAsync(bottleType);

			_logger.LogInformation($"找到 {bottleLocations.Count} 个已有瓶子的位置和 {emptyLocations.Count} 个空位置");

			//如果count大于bottleLocations.Count，则直接返回
			if (count > bottleLocations.Count)
			{
				_logger.LogError($"预留 {bottleType} 瓶子数量不足，需要 {count} 个，但只有 {bottleLocations.Count} 个");
				return;
			}

			int reserved = 0;

			// 首先处理已有瓶子的位置
			foreach (var location in bottleLocations)
			{
				if (reserved >= count)
					break;

				try
				{
					// 再次确认位置状态（避免并发问题）- 强制从数据库获取最新数据
					var freshLocation = await _storageDomainService.GetShelfLocationAsync(location.LocationCode, location.Position);

					if (freshLocation == null)
					{
						_logger.LogWarning($"货架位置 {location.Position} 不存在，跳过");
						continue;
					}

					if (freshLocation.IsReserved != 0)
					{
						_logger.LogWarning($"货架位置 {location.Position} 已被预占（IsReserved={freshLocation.IsReserved}），跳过");
						continue;
					}

					// 使用StorageLocation的方法更新预占位状态
					_logger.LogInformation($"准备更新货架位置 {freshLocation.Position} 的预占位状态，当前IsReserved={freshLocation.IsReserved}");
					freshLocation.UpdateIsReserved(1);
					_logger.LogInformation($"已更新货架位置 {freshLocation.Position} 的预占位状态为 IsReserved={freshLocation.IsReserved}");

					// 更新数据库
					await _storageDomainService.UpdateShelfLocationAsync(freshLocation);

					// 验证更新是否生效
					var verifyLocation = await _storageDomainService.GetShelfLocationAsync(location.LocationCode, location.Position);
					_logger.LogInformation($"验证：货架位置 {verifyLocation?.Position} 的预占位状态为 IsReserved={verifyLocation?.IsReserved}");

					_logger.LogInformation($"已将货架位置 {freshLocation.Position} 的已有 {bottleType} 瓶子设置为预占位状态");
					reserved++;
				}
				catch (Exception ex)
				{
					_logger.LogError(ex, $"处理货架位置 {location.Position} 时发生错误: {ex.Message}");
				}
			}

			// 如果已有瓶子不够，则预留空位置
			if (reserved < count)
			{
				int remainingCount = count - reserved;

				if (emptyLocations.Count < remainingCount)
				{
					_logger.LogWarning($"空位置不足，需要 {remainingCount} 个，但只找到 {emptyLocations.Count} 个");
				}

				foreach (var location in emptyLocations)
				{
					if (reserved >= count)
						break;

					try
					{
						// 再次确认位置状态（避免并发问题）- 强制从数据库获取最新数据
						var freshLocation = await _storageDomainService.GetShelfLocationAsync(location.LocationCode, location.Position);

						if (freshLocation == null)
						{
							_logger.LogWarning($"货架位置 {location.Position} 不存在，跳过");
							continue;
						}

						if (freshLocation.IsReserved != 0)
						{
							_logger.LogWarning($"货架位置 {location.Position} 已被预占（IsReserved={freshLocation.IsReserved}），跳过");
							continue;
						}

						if (freshLocation.IsOccupied)
						{
							_logger.LogWarning($"货架位置 {location.Position} 已被占用，跳过");
							continue;
						}

						// 使用StorageLocation的方法更新预占位状态
						_logger.LogInformation($"准备更新货架位置 {freshLocation.Position} 的预占位状态，当前IsReserved={freshLocation.IsReserved}");
						freshLocation.UpdateIsReserved(1);
						_logger.LogInformation($"已更新货架位置 {freshLocation.Position} 的预占位状态为 IsReserved={freshLocation.IsReserved}");

						// 更新数据库
						await _storageDomainService.UpdateShelfLocationAsync(freshLocation);

						// 验证更新是否生效
						var verifyLocation = await _storageDomainService.GetShelfLocationAsync(location.LocationCode, location.Position);
						_logger.LogInformation($"验证：货架位置 {verifyLocation?.Position} 的预占位状态为 IsReserved={verifyLocation?.IsReserved}");

						_logger.LogInformation($"已将货架空位置 {freshLocation.Position} 设置为预占位状态，用于后续放置 {bottleType} 瓶子");
						reserved++;
					}
					catch (Exception ex)
					{
						_logger.LogError(ex, $"处理货架位置 {location.Position} 时发生错误: {ex.Message}");
					}
				}
			}

			_logger.LogInformation($"成功预留 {reserved}/{count} 个 {bottleType} 类型的瓶子");
		}

		Task<Guid?> ITaskSchedulingDomainService.GetCurrentExperimentGroupIdAsync()
		{
			throw new NotImplementedException();
		}

		Task ITaskSchedulingDomainService.SetCurrentExperimentGroupAsync(Guid? experimentGroupId)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 根据实验ID获取实验对象
		/// </summary>
		/// <param name="experimentId">实验ID</param>
		/// <returns>实验对象，如果未找到则返回null</returns>
		public async Task<Experiment> GetExperimentByIdAsync(Guid experimentId)
		{
			try
			{
				_logger.LogInformation($"根据ID获取实验: {experimentId}");

				// 首先检查当前实验是否匹配ID
				if (_currentExperiment != null && _currentExperiment.ExperimentId == experimentId)
				{
					return _currentExperiment;
				}

				// 如果不是当前实验，则从仓储中查找
				var experiment = await _experimentRepository.GetByIdAsync(experimentId);

				if (experiment == null)
				{
					_logger.LogWarning($"未找到ID为 {experimentId} 的实验");
				}

				return experiment;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"根据ID {experimentId} 获取实验时出错");
				return null;
			}
		}
	}
}